package com.xms.sdk.api.controller;

import com.xms.core.data.Entity;
import com.xms.core.exception.XmsException;
import com.xms.core.model.PagedList;
import com.xms.schema.service.attribute.IAttributeFinderService;
import com.xms.schema.service.entity.IEntityFinderService;
import com.xms.sdk.api.model.RetrieveByAttributeModel;
import com.xms.sdk.api.model.RetrieveMultipleModel;
import com.xms.sdk.core.query.OrderExpression;
import com.xms.sdk.core.query.OrderType;
import com.xms.sdk.core.query.PagingInfo;
import com.xms.sdk.core.query.QueryByAttribute;
import com.xms.sdk.extensions.EntityWrapper;
import com.xms.sdk.service.IDataFinder;
import com.xms.utils.JsonUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import com.xms.web.framework.controller.ApiBaseController;
import com.xms.web.framework.model.JsonResultObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * DataFinderController
 * </p>
 *
 * @author migo
 * @since 2021/9/9
 */
@Api(value = "实体数据查询接口")
@RestController
@RequestMapping("{org}/api/data/retrieve")
public class DataFinderController extends ApiBaseController {
    private IEntityFinderService _entityFinderService;
    private IAttributeFinderService _attributeFinderService;
    private IDataFinder _dataFinder;

    @Autowired
    public DataFinderController(IEntityFinderService entityFinderService
            , IAttributeFinderService attributeFinderService
            , IDataFinder dataFinder) {
        _entityFinderService = entityFinderService;
        _attributeFinderService = attributeFinderService;
        _dataFinder = dataFinder;
    }

    @ApiOperation("查找引用记录")
    @RequestMapping(value = "referencedrecord/{entityid}/{value}", method = RequestMethod.GET)
    public JsonResultObject retrieveReferencedRecord(@PathVariable(value = "entityid", required = true) UUID entityId,
                                                     @PathVariable(value = "value", required = true) String value,
                                                     @RequestParam(value = "allcolumns", required = false) Boolean allColumns) throws Exception {
        if (entityId.equals(UUIDUtil.Empty) || value.isEmpty()) {
            return JNotFound();
        }
        com.xms.schema.entity.Entity entity = _entityFinderService.getById(entityId);
        if (entity == null) {
            return JNotFound();
        }
        String entityName = entity.getName();
        QueryByAttribute qba = new QueryByAttribute(entityName);
        allColumns = allColumns == null ? false : allColumns;
        if (allColumns) {
            qba.ColumnSet.AllColumns = true;
        } else {
            qba.ColumnSet.addColumns(entityName + "id", "name");
        }
        qba.addCondition(entityName + "id", value);

        com.xms.core.data.Entity result = _dataFinder.retrieve(qba);
        if (result != null && !result.isEmpty()) {
            if (!allColumns) {
                result.addIfNotContain("id", result.getIdValue());
                result.remove(entityName + "id");
            } else {
                result = EntityWrapper.wrapOptionName(_attributeFinderService.getByEntityId(entityId), result);
            }
        }

        return JOk(result);
    }

    @ApiOperation("查找一条记录")
    @PostMapping(value = "single")
    public JsonResultObject retrieve(@RequestBody RetrieveMultipleModel args) throws Exception {
        if (args.query.EntityName.isEmpty()) {
            return JError("entityname is not specified");
        }
        boolean existsName = _entityFinderService.existsName(args.query.EntityName);
        if (!existsName) {
            return JError("entityname is not found");
        }

        com.xms.core.data.Entity result = _dataFinder.retrieve(args.query);

        return JOk(result);
    }

    @ApiOperation("查找一条记录")
    @RequestMapping(value = "{entityname}/{id}", method = RequestMethod.GET)
    public JsonResultObject retrieveById(@PathVariable(value = "entityname", required = true) String entityName,
                                         @PathVariable(value = "id", required = true) UUID id) throws Exception {
        if (entityName.isEmpty()) {
            return JError("entityname is not specified");
        }
        boolean existsName = _entityFinderService.existsName(entityName);
        if (!existsName) {
            return JError("entityname is not found");
        }

        Entity result = _dataFinder.retrieveById(entityName, id);

        return JOk(result);
    }

    @ApiOperation("查找一条记录")
    @PostMapping(value = "byattribute")
    public JsonResultObject retrieveByAttribute(@RequestBody RetrieveByAttributeModel model) {
        if (StringUtil.isEmpty(model.entityName)) {
            return JError("entityname is not specified");
        }
        try {
            HashMap<String, Object> filter = JsonUtil.arrayToHashMap(model.filter);
            return JOk(_dataFinder.retrieveByAttribute(model.entityName, filter));
        } catch (Exception e) {
            e.printStackTrace();
            return JError(e.getMessage());
        }
    }

    @ApiOperation("查找多条记录")
    @PostMapping(value = "multiplebyattribute")
    public JsonResultObject multipleByAttribute(@RequestBody RetrieveByAttributeModel model) {
        if (StringUtil.isEmpty(model.entityName)) {
            return JError("entityname is not specified");
        }
        try {
            HashMap<String, Object> filter = JsonUtil.arrayToHashMap(model.filter);
            return JOk(_dataFinder.retrieveMultipleByAttribute(model.entityName, filter));
        } catch (Exception e) {
            e.printStackTrace();
            return JError(e.getMessage());
        }
    }

    @ApiOperation("查找多条记录")
    @PostMapping(value = "multiple", produces = "application/json;charset=UTF-8")
    public JsonResultObject retrieveMultiple(@RequestBody RetrieveMultipleModel args) throws Exception {
        if (args.query == null || StringUtil.isEmpty(args.query.EntityName)) {
            return JError("entityname is not specified");
        }
        /*boolean existsName = _entityFinderService.existsName(args.query.EntityName);
        if (!existsName)
        {
            return JError("entityname is not found");
        }*/
        if (args.isAll != null && args.isAll) {
            List<Entity> result = _dataFinder.retrieveAll(args.query);
            return JOk(result);
        } else {
            if (args.query.PageInfo == null) {
                args.query.PageInfo = new PagingInfo(1, 10);
            }
            PagedList<Entity> pagedList = _dataFinder.retrieveMultiple(args.query);
            return JOk(pagedList);
        }
    }

    /**
     * 查找所有记录, 路由示例：/all/customer/name,leadid/name:asc
     *
     * @param entityName 实体名称
     * @param columns    以半角逗号分隔的查询列名，allcolumn代表查询所有列
     * @param orderby    排序方式, 字段:升序或降序
     * @return
     * @throws XmsException
     * @throws SQLException
     */
    @ApiOperation("查找所有记录")
    @RequestMapping(value = "all/{entityname}/{columns}/{orderby}", method = RequestMethod.GET)
    public JsonResultObject retrieveAll(@PathVariable(value = "entityname", required = true) String entityName,
                                        @PathVariable(value = "columns", required = false) String columns,
                                        @PathVariable(value = "orderby", required = false) String orderby) throws XmsException, SQLException {
        if (entityName.isEmpty()) {
            return JError("entityname is not specified");
        }
        com.xms.schema.entity.Entity entity = _entityFinderService.getByName(entityName);
        if (entity == null) {
            return JError("entityname is not found");
        }
        List<String> columnNames = StringUtil.notEmpty(columns) ? (columns.equalsIgnoreCase("allcolumn") ? null : Arrays.asList(StringUtil.splitSafe(columns, ","))) : null;
        OrderExpression order = null;
        if (StringUtil.notEmpty(orderby)) {
            String[] orderValues = StringUtil.splitSafe(orderby, ":");
            if (orderValues.length > 0) {
                order = new OrderExpression(orderValues[0], orderValues.length > 1 && orderValues[1].equalsIgnoreCase("asc") ? OrderType.Ascending : OrderType.Descending);
            }
        }
        List<Entity> result = _dataFinder.retrieveAll(entityName, columnNames, order);
        return JOk(result);
    }
}
